import 'dart:developer';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:get/get.dart';
import 'package:im_base/private/app_ext.dart';
import 'package:im_base/public/ext/im_base_controller.dart';
import 'package:im_base/public/global/global.dart';
import 'package:im_base/public/global/im_keys.dart';
import 'package:im_base/public/service/tim_service.dart';
import 'package:path_provider/path_provider.dart';
import 'package:tencent_im_sdk_plugin/enum/message_elem_type.dart';
import 'package:tencent_im_sdk_plugin/models/v2_tim_message.dart';
import 'package:tencent_im_sdk_plugin/models/v2_tim_value_callback.dart';
import 'package:im_base/public/ext/string_ext.dart';
import '../../../../im_base.dart';
import 'package:logger/logger.dart';
import 'input/logic.dart';
import 'items/audio/logic.dart';
import 'state.dart';

final String POP_MENU = "popMenu";

class ChatLogic extends IMBaseController {
  final state = ChatState();
  FlutterSoundRecorder? record;
  FlutterSoundPlayer? _player;
  String? temPath;
  Function(String, String)? headerTap;

  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onReady() {
    getHistory();
    initRecord();
    watchListScroll();
    watchMessage();
    watchWithdraw();
    watchSendProgress();
    super.onReady();
  }

  @override
  void onClose() {
    record?.closeAudioSession();
    record = null;
    _player?.closeAudioSession();
    _player = null;
    state.chatController?.dispose();
    state.chatController = null;
    super.onClose();
  }

  ///尝试解决controller没有正常删除问题，如果新会话的id不等于当前获取的id，则直接重新进行加载
  void refreshData({required String id, required bool isGroup}) {
    if (state.id != id) {
      state.id = id;
      state.isGroup = isGroup;
      state.lastMsgId = null;
      getHistory();
    }
  }

  ///加载更多
  void loadMore() {
    if (state.loadMore) {
      state.lastMsgId = state.chatHistory.last.msgID;
      getHistory();
    }
  }

  ///头像点击事件
  void headerClick(String? userID, String name) {
    headerTap?.call(userID ?? '', name);
  }

  ///查看聊天记录中所有的图片列表
  void checkPhotoList(String imgUrl) {
    if (state.photoList.isEmpty) {
      toCheckPhoto([imgUrl], 0);
    } else {
      var index =
          state.photoList.indexWhere((e) => imgUrl.contains(e) || e == imgUrl);
      toCheckPhoto(state.photoList, index);
    }
  }

  ///监听对方消息撤回
  void watchWithdraw() {
    addKeyListener(IMKeys.withdrawMessage, (data) {
      if (data is V2TimMessage) {
        if (data.sender == state.id) {
          updateMessageStatus(data.msgID ?? '', 6);
        }
      }
    });
  }

  ///监听消息发送进度
  void watchSendProgress() {
    addKeyListener(IMKeys.sendMsgProgress, (data) {
      if (data is V2TimMessage) {
        addImageAudioMessage(data, 0);
      }
    });
  }

  ///获取历史记录
  void getHistory() async {
    if (state.isGroup) {
      TimService.instance.v2timManager
          ?.getMessageManager()
          .getGroupHistoryMessageList(
              groupID: state.id ?? "",
              count: state.pageSize,
              lastMsgID: state.lastMsgId)
          .then((value) => dealData(value));
    } else {
      TimService.instance.v2timManager
          ?.getMessageManager()
          .getC2CHistoryMessageList(
              userID: state.id ?? "",
              count: state.pageSize,
              lastMsgID: state.lastMsgId)
          .then((value) => dealData(value));
    }
  }

  ///统一处理获取到的消息记录
  void dealData(V2TimValueCallback<List<V2TimMessage>> value) {
    if (value.code == 0) {
      state.status = LoadStatus.FINISHED;
      state.loadMore =
          value.data != null && value.data!.length >= state.pageSize;
      state.chatHistory.addAll(value.data ?? List.empty());
    } else {
      state.status = LoadStatus.ERROR;
    }
    dealImage(state.chatHistory
        .where((element) =>
            element.elemType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE)
        .toList());
    state.chatHistory
        .sort((left, right) => right.timestamp!.compareTo(left.timestamp!));
    update();
  }

  ///添加新消息,同时进行排序
  void addNewMessage(V2TimMessage message) {
    if (message.userID != state.id && message.groupID != state.id) {
      ///如果消息不属于当前会话,则不添加消息
      return;
    }
    if (message.sender != Global.IDENTIFIER &&
        message.elemType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE) {
      ///如果当前消息是自己发送的并且是图片消息,则直接将图片链接添加到图片列表中
      addImage(message);
    }
    if (message.faceUrl.isNullEmpty()) {
      message.faceUrl = Global.header;
    }
    if (state.chatHistory.any((element) => element.msgID == message.msgID)) {
      ///如果消息已经在列表中,则不再进行添加
      return;
    }
    TimService.instance.markMessageReadById(state.id!, state.isGroup);
    state.chatHistory.add(message);
    state.chatHistory
        .sort((left, right) => right.timestamp!.compareTo(left.timestamp!));
    update();
    scrollBottom();
  }

  void scrollBottom() {
    state.chatController?.jumpTo(-10);
  }

  ///在发送图片消息时,先将该条消息插入到消息列表,等发送成功之后再进行更新
  void addImageAudioMessage(V2TimMessage message, int progress) {
    final oldMessage =
        state.chatHistory.where((element) => element.msgID == message.msgID);
    if (oldMessage.isEmpty) {
      addNewMessage(message);
      update();
    }
  }

  ///图片消息发送成功之后,更新该条消息
  void updateImageAudioMessage(V2TimMessage message) {
    message.progress = 100;
    final index = state.chatHistory
        .lastIndexWhere((element) => element.msgID == message.msgID);
    try {
      state.chatHistory.replaceRange(index, index + 1, [message]);
    } on RangeError {
      addNewMessage(message);
    }

    update();
  }

  ///初始化录音
  void initRecord() async {
    await getTemporaryDirectory().then((value) => temPath = value.path);
    record = FlutterSoundRecorder(logLevel: Level.error);
    await record
        ?.openAudioSession(
            mode: SessionMode.modeVoiceChat, category: SessionCategory.record)
        .then((value) {
      record!.setSubscriptionDuration(Duration(milliseconds: 100));
      value!.dispositionStream()!.listen((event) {
        Get.find<InputLogic>(tag: state.id).updateVoice(event.decibels ?? 0);
        state.recordLength = event.duration.inSeconds;
      });
    });

    _player = FlutterSoundPlayer(logLevel: Level.error);
    await _player
        ?.openAudioSession()
        .then((value) => value?.dispositionStream()?.listen((event) {
              log('FlutterSoundPlayer--${event.duration.inSeconds}--${event.position}');
            }));
  }

  ///播放语音,判断本地是否有该语音文件,如果有则播放本地文件,没有播放网络音频
  ///如果当前没有播放的语音消息,或者当前播放消息跟再次播放的消息为同一条,则直接进行播放,同时通知item进行动画播放
  ///每次播放前先调用stopPlay接口,防止同时播放多个语音消息
  void playAudio(String url, String path, String msgId) async {
    if (state.currentPlayAudioMsgId != null &&
        state.currentPlayAudioMsgId != msgId) {
      Get.find<AudioLogic>().stopPlay(state.currentPlayAudioMsgId ?? "");
      Get.find<AudioLogic>().startPlay(msgId);
    } else {
      Get.find<AudioLogic>().startPlay(msgId);
    }
    state.currentPlayAudioMsgId = msgId;

    if (File(path).existsSync()) {
      await _player?.startPlayer(
          fromURI: path,
          codec: Codec.aacMP4,
          whenFinished: () {
            ///播放完成之后,更改状态
            stopAudio(null, null, null);
          });
    } else {
      await _player?.startPlayer(
          fromURI: url,
          codec: Codec.aacMP4,
          whenFinished: () {
            ///播放完成之后,更改状态
            stopAudio(null, null, null);
          });
    }
  }

  ///停止播放语音
  ///停止播放将当前记录的语音消息置为null
  void stopAudio(String? url, String? path, String? msgId) async {
    Get.find<AudioLogic>().stopPlay(state.currentPlayAudioMsgId ?? "");
    state.currentPlayAudioMsgId = null;
    if (msgId.isNullEmpty()) {
      return;
    }
    await _player?.stopPlayer();
  }

  ///开始录音
  void startRecord() async {
    await record?.startRecorder(
        codec: Codec.aacMP4,
        toFile: "$temPath/${DateTime.now().millisecondsSinceEpoch}.aac");
  }

  ///停止录音
  void stopRecord() async {
    await record?.stopRecorder().then((value) {
      dealRecord(value);
    });
  }

  void dealRecord(String? path) {
    if (path.isNullEmpty()) {
      showToast("录音失败");
      return;
    }
    if (state.cancleAudio) {
      ///如果取消发送,则不执行发送操作,同时状态置为false
      state.cancleAudio = false;
      return;
    }
    if (state.recordLength < 1) {
      showToast("录音时间过短");
    } else {
      TimService.instance.sendAudioMessage(
          path!, state.recordLength, state.id ?? "", state.isGroup,
          callBack: (result) {
        if (result.code == 0) {
          updateImageAudioMessage(result.data!);
        } else {
          showToast("消息发送失败[${result.code}]|${result.desc}");
        }
      });
    }
  }

  ///展示弹出菜单
  void showPopMenu(
      Offset offset, String msgId, bool isSelf, int msgTime, String content) {
    state.canWithdraw =
        DateTime.now().millisecondsSinceEpoch / 1000 - msgTime <= 5 * 60;
    state.content = content;
    state.isSelf = isSelf;
    state.showPopMenu = true;
    state.currendMsgID = msgId;
    state.positionX = state.canWithdraw ? offset.dx - 60 : offset.dx - 50;
    state.positionY = offset.dy - Get.statusBarHeight;
    update([POP_MENU]);
  }

  ///隐藏弹出菜单
  void hidePopMenu() {
    state.showPopMenu = false;
    update([POP_MENU]);
  }

  ///隐藏键盘,隐藏菜单,隐藏底部弹出菜单
  void hideAllPop() {
    hidePopMenu();
    hideSoftKeyboard();

    if (!Get.find<InputLogic>(tag: state.id).state.isAudio) {
      Get.find<InputLogic>(tag: state.id).hideEmoji();
      Get.find<InputLogic>(tag: state.id).showMore(show: false);
    }
  }

  ///监听列表滚动
  void watchListScroll() {
    state.chatController?.addListener(() {
      hidePopMenu();
    });
  }

  ///删除消息
  void deleteMessage(String msgId) async {
    hidePopMenu();
    TimService.instance.deleteMessage(msgId, callBack: (value) {
      if (value.code == 0) {
        state.chatHistory.removeWhere((element) => element.msgID == msgId);
        update();
      }
    });
  }

  ///撤回消息
  void withDrawMessage(String msgId) async {
    hidePopMenu();
    TimService.instance.withDrawMessage(msgId, callBack: (value) {
      updateMessageStatus(msgId, 6);
    });
  }

  ///更新撤回消息状态[status] 等于6为撤回状态
  void updateMessageStatus(String msgID, int status) {
    try {
      state.chatHistory
          .where((element) => element.msgID == msgID)
          .first
          .status = status;
      update();
    } catch (e) {}
  }

  ///监听新的消息
  void watchMessage() {
    addKeyListener(state.id ?? "", (message) {
      addNewMessage(message);
    });
  }

  ///将所有的图片链接取出
  void dealImage(List<V2TimMessage> images) async {
    images.forEach((element) {
      addImage(element);
    });
  }

  void addImage(V2TimMessage element) {
    var image = element.imageElem!.imageList;
    if (image != null) {
      var bigImage = GetPlatform.isAndroid
          ? image.where((element) => element?.type == 0).isEmpty
              ? null
              : image.where((element) => element?.type == 0).first
          : image.where((element) => element?.type == 1).isEmpty
              ? null
              : image.where((element) => element?.type == 1).first;
      if (bigImage == null) {
        bigImage = image.where((element) => element?.type == 1).first;
      }

      if (bigImage != null) {
        state.photoList.insert(0, bigImage.url ?? '');
      }
    }
  }
}
